﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Simhopp.Database;
using System.Windows.Forms;

namespace Simhopp.Model
{
    public class Competition : InterfaceCompetitionModel
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public DateTime Date { get; set; }
        public string Location { get; set; }
        public Height Height { get; set; }
        public char Gender { get; set; }
        public AgeClass AgeClass { get; set; }
        public CompetitionType Event { get; set; }
        public List<Judge> JudgeList { get; set; }
        public List<Diver> DiverList { get; set; }
        public List<Dive> AllDiveList { get; set; }
        public int CompetingDivers { get; set; }
        public int RoundsInCompetition { get; set; }
        public int Round { get; set; }
        public int DiverUpNext { get; set; }
        public int JudgingJudges { get; set; }
        public Countries Country { get; set; }


        public Competition()
        {
            this.Name = "";
            this.ID = 0;
            JudgeList = new List<Judge>();
            DiverList = new List<Diver>();
            AllDiveList = new List<Dive>();
            this.Gender = ' ';
            this.Date = new DateTime();
            this.Location = "";
            this.CompetingDivers = 0;
            this.RoundsInCompetition = 0;
            this.Round = 0;
            this.DiverUpNext = 0;
            this.JudgingJudges = 0;
        }
        public Competition(string Name, CompetitionType Event, string Location, DateTime Date, Height Height, 
            AgeClass AgeClass, char Gender, int JudgingJudges, int RoundsInCompetition)
        {
            this.ID = 0;
            this.Name = Name;
            JudgeList = new List<Judge>();
            DiverList = new List<Diver>();
            AllDiveList = new List<Dive>();
            this.Location = Location;
            this.Gender = Gender;
            this.AgeClass = AgeClass;
            this.Height = Height;
            this.CompetingDivers = 0;
            this.JudgingJudges = JudgingJudges;
            this.RoundsInCompetition = RoundsInCompetition;
            this.Round = 1;
            this.DiverUpNext = 1;
            this.Event = Event;
            this.Date = Date;
        }
        public Competition(int ID, string Name, CompetitionType Event, string Location, DateTime Date, 
            Height Height, AgeClass AgeClass, char Gender, int JudgingJudges, int RoundsInCompetition)
        {
            this.ID = ID;
            this.Name = Name;
            JudgeList = new List<Judge>();
            DiverList = new List<Diver>();
            AllDiveList = new List<Dive>();
            this.Location = Location;
            this.Height = Height;
            this.AgeClass = AgeClass;
            this.Gender = Gender;
            this.CompetingDivers = 0;
            this.JudgingJudges = JudgingJudges;
            this.RoundsInCompetition = RoundsInCompetition;
            this.Round = 1;
            this.DiverUpNext = 1;
            this.Event = Event;
            this.Date = Date;
        }
        public override string ToString()
        {
            return this.Name + " : "+ this.Date.ToShortDateString();
        }
        public void AddJudge(Judge judge)
        {
            // Check if empty boxes
            // Check if valid strings
            // Check if valid password
            DBConnect dbc = new DBConnect();
            int ID = 0;
            JudgeList.Add(judge);
            ID = dbc.AddJudge(judge.Name, judge.Nationality, judge.Password,
                judge.Username, this.ID);
            judge.ID = ID;
        }
        public void RemoveJudge(int ID)
        {
            DBConnect dbc = new DBConnect();
            Judge judge = GetJudge(ID);
            if (judge != null)
                JudgeList.Remove(judge);
            dbc.RemoveJudge(judge.ID);
        }
        public void UpdateJudge(int ID, string Name, Countries Nationality, string Password, string Username)
        {
            DBConnect dbc = new DBConnect();
            Judge judge = GetJudge(ID);
            if (judge != null)
            {
                judge.Name = Name;
                judge.Nationality = Nationality;
                judge.Password = Password;
                judge.Username = Username;
            }
            dbc.UpdateJudge(judge.ID, judge.Name, judge.Nationality, judge.Password,
                judge.Username, 0);
        }
        public void AddDiver(Diver diver)
        {
            DBConnect dbc = new DBConnect();
            int ID = 0;
            DiverList.Add(diver);
            ID = dbc.AddDiver(diver.Name, diver.DateOfBirth, diver.Gender, diver.StartNumber,
                diver.TotalPoints, diver.Nationality, this.ID);
            diver.ID = ID;
        }
        public void RemoveDiver(Diver diver)
        {
            DBConnect dbc = new DBConnect();
            DiverList.Remove(diver);
            dbc.RemoveDiver(diver.ID);
        }
        public void UpdateDiver(Diver originalDiver, Diver updatedDiver)
        {
            DBConnect dbc = new DBConnect();
            originalDiver.Name = updatedDiver.Name;
            originalDiver.DateOfBirth = updatedDiver.DateOfBirth;
            originalDiver.StartNumber = updatedDiver.StartNumber;
            originalDiver.DateOfBirth = updatedDiver.DateOfBirth;
            originalDiver.Gender = updatedDiver.Gender;
            originalDiver.TotalPoints = updatedDiver.TotalPoints;
            originalDiver.Nationality = updatedDiver.Nationality;
            dbc.UpdateDiver(originalDiver.ID, originalDiver.Name, originalDiver.DateOfBirth,
                originalDiver.Gender, originalDiver.StartNumber, originalDiver.TotalPoints,
                originalDiver.Nationality, this.ID);
        }
        public void AccessStartList() { }
        public Judge GetJudge(int ID)
        {
            foreach (var judge in JudgeList)
            {
                if (judge.ID == ID)
                    return judge;
            }
            return null;
        }
        public Diver GetDiverByNumber(int StartNumber)
        {
            foreach (Diver diver in DiverList)
            {
                if (diver.StartNumber == StartNumber)
                    return diver;
            }
            return null;
        }
        public Diver GetDiver(int ID)
        {
            foreach (var diver in DiverList)
            {
                if (diver.ID == ID)
                    return diver;
            }
            return null;
        }
        public void MoveDiverToBack(Diver diver)
        {
            DiverList.Remove(diver);
            DiverList.Insert(DiverList.Count, diver);
        }
        public List<Dive> GetAllDives()
        {
            DBConnect dbc = new DBConnect();
            dbc.GetAllDives(AllDiveList);
            return AllDiveList;
        }
        public void GetDivesForDiver(DBConnect dbc)
        {
            foreach (Diver d in DiverList)
            {
                d.GetDivesForDiver(dbc);
            }
        }
        public void GetCompleteJudgeList(List<Judge> completeJudgeList)
        {
            DBConnect dbc = new DBConnect();
            dbc.GetAllJudge(completeJudgeList);
        }
        public void GetCompleteDiverList(List<Diver> completeDiverList)
        {
            DBConnect dbc = new DBConnect();
            dbc.GetAllDiver(completeDiverList);
        }
        public void AddExistingJudge(Judge judge)
        {
            
            DBConnect dbc = new DBConnect();
            dbc.AddJudgeToCompetition(judge.ID, this.ID);
            UpdateJudgeListFromDatabase();
        }

        public void AddExistingDiver(Diver diver)
        {
            DBConnect dbc = new DBConnect();
            dbc.AddDiverToCompetition(diver.ID, this.ID, 0, 0);
            UpdateDiverListFromDatabase();
        }

        public void UpdateDiverListFromDatabase()
        {
            DiverList.Clear();
            DBConnect dbc = new DBConnect();
            dbc.GetDiverWithCompetitionID(this.ID, DiverList);
        }

        public void UpdateJudgeListFromDatabase()
        {
            JudgeList.Clear();
            DBConnect dbc = new DBConnect();
            dbc.GetJudgesWithCompetitionID(this.ID, JudgeList);
        }
        public bool MakeSureCompetitionIsReadyToStart()
        {
            if(this.DiverList.Count == 0)
            {
                MessageBox.Show("No divers in competition");
                return false;
            }
            int NumberOfDives = this.DiverList[0].DiveList.Count;          
            List<Diver> WrongStartNumber = new List<Diver>();
            List<Diver> WrongNumberOfDives = new List<Diver>();
            Dictionary<Dive, Diver> WrongDiveNumber = new Dictionary<Dive, Diver>();
            bool NumberOfDivesFlag = true;
            bool StartNumberFlag = true;
            bool DiveNumberFlag = true;
            for (int y = 0; y < this.DiverList.Count; y++)
            {
                if (this.DiverList[y].StartNumber != y + 1)
                {
                    StartNumberFlag = false;
                    WrongStartNumber.Add(this.DiverList[y]);
                }
                if (this.DiverList[y].DiveList.Count != NumberOfDives)
                {
                    NumberOfDivesFlag = false;
                    WrongNumberOfDives.Add(this.DiverList[y]);
                }

                for (int i = 0; i < this.DiverList[y].DiveList.Count; i++)
                {
                    if (this.DiverList[y].DiveList[i].DiveNumber != i + 1)
                    {
                        DiveNumberFlag = false;
                        WrongDiveNumber.Add(this.DiverList[y].DiveList[i], this.DiverList[y]);
                    }
                }
            }

            if (NumberOfDives == 0)
            {
                MessageBox.Show("Can't have a competition without any dives right?");
                return false;
            }
            if (StartNumberFlag && NumberOfDivesFlag && DiveNumberFlag)
                return true;
            if (!StartNumberFlag)
            {
                string s = "";
                foreach (Diver diver in WrongStartNumber)
                {
                    s += "\n" + diver.Name;
                }
                MessageBox.Show("Incorrect Start numbers: " + s);
            }
            if (!NumberOfDivesFlag)
            {
                string s = "";
                foreach (Diver diver in WrongNumberOfDives)
                {
                    s += "\n" + diver.Name;
                }
                MessageBox.Show("Incorrect number of Dives: " + s);
            }
            if (!DiveNumberFlag)
            {
                string s = "";
                foreach (var dive in WrongDiveNumber)
                {
                    s += "\n" + dive.Value.Name + ":" + dive.Key.Name;
                }
                MessageBox.Show("Incorrect Dive numbers: " + s);

            }
            return false;
        }
    }
}

